package org.meichao.thread;

import java.util.concurrent.*;

/**
 * 构造多线程执行队列对象
 */
public class MultiTaskPool {

    //执行计划的线程池
    private static ExecutorService executor = null;

    //使用单例模式
    private static class LazyLoad{
        private static final MultiTaskPool MULTI_TASK_POOL = new MultiTaskPool();
    }

    //获取当前实例
    public static final MultiTaskPool getInstance(){
        return LazyLoad.MULTI_TASK_POOL;
    }

    /**
     * 构造函数
     * 线程池流程:
     *  1.当正在执行任务的线程数量 < corePoolSize时，线程池将启动一个核心线程执行任务，即使此时线程池中存在空闲线程
     *  2.当corePoolSize < 正在执行任务的线程数量 < maximumPoolSize时，新提交的线程将被放入workQueue中
     *  3.如果工作队列也满了，这个时候线程池中剩下的线程（除核心线程以外的线程）就会启动来帮助核心线程执行任务
     *  4.如果线程数已达到上限，这时就没法正常处理新到的任务，新的任务就会被交给"拒绝策略"来处理了
     *
     * RejectedExecutionHandler : "拒绝策略",当任务无法执行时的处理器
     *  当队列满时，submit()一个task会导致调用我们自定义的RejectedExecutionHandler，
     *  而我们自定义的RejectedExecutionHandler会保证该task继续被尝试用阻塞式的put()到队列中
     */
    private MultiTaskPool(){
        executor = new ThreadPoolExecutor(10, 100, 0L,
                TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(3000), Executors.defaultThreadFactory(),
                new RejectedExecutionHandler(){
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                        try {
                            //继续加入阻塞队列执行
                            executor.getQueue().put(r);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }

    /**
     * 线程池执行任务方法-无返回值
     */
    public void executeTask(Runnable task){
        executor.execute(task);
    }

    /**
     * 线程池执行任务方法-有返回值
     * public <T>这个T是个修饰符的功能，表示是个泛型方法，就像有static修饰的方法是个静态方法一样
     */
    public <T> Future<T> executeTaskReturn(Callable<T> task){
        return executor.submit(task);
    }

}
